﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using SIG.Core;
using SIG.Infrastructure.Logging;
using SIG.Data.UnitOfWork;
using SIG.Infrastructure.Cache;
using System.Reflection;
using System.Text;
using SIG.Resources.Admin;

namespace SIG.Service
{
    public abstract class EntityService<T> : IEntityService<T> where T : BaseEntity
    {
      //  private readonly Type typeObject = typeof(T);
        private readonly PropertyInfo[] properties = typeof(T).GetProperties();
        //  IUnitOfWork _unitOfWork;
        private IRepository<T> _repository;
        private ICacheService _cacheService;
        private ILoggingService _logger;
        public EntityService(IRepository<T> repository, ICacheService cacheService,  ILoggingService logger)
        {            
            _repository = repository;
            _cacheService = cacheService;
            _logger = logger;

    }
        
    public virtual T GetById(object id)
        {
            return _repository.GetElementById(id);
           

        }
       public virtual  IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
        {
            return _repository.GetFilteredElements(predicate);
        }
        public virtual void Create(T entity)
        {

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            IMainBCUnitOfWork unitOfWork = this._repository.UnitOfWork as IMainBCUnitOfWork;
            _repository.Add(entity);

            BaseEntity baseEntity = entity as BaseEntity;
            _cacheService.Invalidate(baseEntity.EntityName);

            string logBody = LogBody(entity);
            
            _logger.Info(string.Format(Logs.CreateMessage, baseEntity.EntityName, logBody));
            unitOfWork.Commit();

        }
        


        public virtual void Update(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");
            IMainBCUnitOfWork unitOfWork = this._repository.UnitOfWork as IMainBCUnitOfWork;
            _repository.SetModified(entity);
        
            BaseEntity baseEntity = entity as BaseEntity;
            _cacheService.Invalidate(baseEntity.EntityName);

            string logBody = LogBody(entity);
            _logger.Info(string.Format(Logs.UpdateMessage, baseEntity.EntityName, logBody));

            unitOfWork.Commit();
        }

        public virtual void Delete(T entity)
        {            
        
            if (entity == null) throw new ArgumentNullException("entity");
            IMainBCUnitOfWork unitOfWork = this._repository.UnitOfWork as IMainBCUnitOfWork;
            _repository.Remove(entity);

            BaseEntity baseEntity = entity as BaseEntity;
            _cacheService.Invalidate(baseEntity.EntityName);

            string logBody = LogBody(entity);
            _logger.Info(string.Format(Logs.DeleteMessage, baseEntity.EntityName, logBody));

            unitOfWork.Commit();
           
        }

        public virtual IQueryable<T> GetAll()
        {
            return _repository.GetAllElements();
        }

        /// <summary>
        /// 获取实体内容
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private string LogBody(T entity)
        {
            StringBuilder sb = new StringBuilder("[");
            foreach (var property in properties)
            {
                
                var name = property.Name;
                if(name == "Id")
                {
                    var value = property.GetValue(entity, null);
                    sb.Append($"{name}:{value}; ");
                }
              
            }
            sb.Append("]");
            return sb.ToString();
        }
    }
}
